package com.kinglone.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;

public class Query<T>
{
  public static Map<String, String> MYSQL_SPECIAL_STR = new HashMap();
  private Class<T> type;
  Map<String, Between> betweens = new HashMap();

  Map<String, Object> params = new HashMap();

  Map<String, Object> paramLikes = new HashMap();

  Map<String, List<Object>> inArrayParams = new HashMap();

  Map<String, Object> gtParams = new HashMap();

  Map<String, Object> ltParams = new HashMap();
  Integer pageNo;
  Integer pageSize;
  List<String> includeField = new ArrayList();

  Map<String, DBOrder> orders = new HashMap();

  public Query(Class<T> type)
  {
    this.type = type;
  }

  public Query addIn(String field, List<Object> list)
  {
    if ((list == null) || (list.size() == 0)) {
      return this;
    }
    this.inArrayParams.put(field, list);
    return this;
  }

  public Query addIn(String field, Object[] objects)
  {
    if ((objects == null) || (objects.length == 0)) {
      return this;
    }

    List list = new ArrayList();
    Collections.addAll(list, objects);
    this.inArrayParams.put(field, list);
    return this;
  }

  public Query addBetween(String fieldName, Long begin, Long end)
  {
    if ((begin == null) || (end == null)) {
      return this;
    }

    if ((begin.longValue() > end.longValue()) || (begin.longValue() == 0L) || (end.longValue() == 0L)) {
      return this;
    }

    this.betweens.put(fieldName, new Between(begin, end));
    return this;
  }

  public Query addBetween(String fieldName, Object begin, Object end) {
    if ((begin == null) || (end == null)) {
      return this;
    }

    this.betweens.put(fieldName, new Between(begin, end));
    return this;
  }

  public Query addEq(String fieldName, Object value)
  {
    if ((value == null) || ("null".equals(value)) || ("NULL".equals(value))) {
      return this;
    }
    this.params.put(fieldName, value);
    return this;
  }

  public Query addGt(String fieldName, Object value)
  {
    if ((value == null) || ("null".equals(value)) || ("NULL".equals(value))) {
      return this;
    }
    this.gtParams.put(fieldName, value);
    return this;
  }

  public Query addLt(String fieldName, Object value)
  {
    if ((value == null) || ("null".equals(value)) || ("NULL".equals(value))) {
      return this;
    }
    this.ltParams.put(fieldName, value);
    return this;
  }

  public Query addLike(String fieldName, String value)
  {
    if ((StringUtils.isEmpty(value)) || ("null".equals(value)) || ("NULL".equals(value))) {
      return this;
    }

    StringBuilder sb = new StringBuilder();
    for (char c : value.toCharArray()) {
      String mysqlChar = (String)MYSQL_SPECIAL_STR.get(c + "");
      if (mysqlChar != null)
        sb.append(mysqlChar);
      else {
        sb.append(c);
      }

    }

    this.paramLikes.put(fieldName, "%" + sb.toString() + "%");
    return this;
  }

  public Query addPrefixLike(String fieldName, String value)
  {
    if (StringUtils.isEmpty(value)) {
      return this;
    }

    StringBuilder sb = new StringBuilder();
    for (char c : value.toCharArray()) {
      String mysqlChar = (String)MYSQL_SPECIAL_STR.get(c + "");
      if (mysqlChar != null)
        sb.append(mysqlChar);
      else {
        sb.append(c);
      }

    }

    this.paramLikes.put(fieldName, sb.toString() + "%");
    return this;
  }

  public Query addIncludeField(String fieldName)
  {
    this.includeField.add(fieldName);
    return this;
  }

  public Query setPaged(int pageNo, int pageSize)
  {
    if (pageNo == 0) {
      pageNo = 1;
    }
    if (pageSize == 0) {
      pageSize = 10;
    }

    this.pageNo = Integer.valueOf(pageNo);
    this.pageSize = Integer.valueOf(pageSize);
    return this;
  }

  public Query addOrder(String name, DBOrder dbOrder)
  {
    this.orders.put(name, dbOrder);
    return this;
  }

  public boolean hasOrder() {
    return (this.orders.size() > 0);
  }

  public boolean isLike(String fieldName) {
    return this.paramLikes.containsKey(fieldName);
  }

  public Map<String, Object> getParams()
  {
    return this.params;
  }

  public Class<T> getType()
  {
    return this.type;
  }

  public Map<String, Between> getBetweens() {
    return this.betweens;
  }

  public Map<String, Object> getParamLikes()
  {
    return this.paramLikes;
  }

  public Integer getPageNo() {
    return this.pageNo;
  }

  public Integer getPageSize() {
    return this.pageSize;
  }

  public Map<String, List<Object>> getInArrayParams() {
    return this.inArrayParams;
  }

  public int getOffset() {
    if ((this.pageNo == null) || (this.pageSize == null)) {
      return -1;
    }

    return ((this.pageNo.intValue() - 1) * this.pageSize.intValue());
  }

  public List<String> getIncludeField()
  {
    return this.includeField;
  }

  public boolean isSearchAllField()
  {
    return this.includeField.isEmpty();
  }

  public boolean isFieldSearch(String fieldName)
  {
    return this.includeField.contains(fieldName);
  }

  public static Query build(Class<?> clazz) {
    return new Query(clazz);
  }

  public Map<String, DBOrder> getOrders() {
    return this.orders;
  }

  public String getExpression(String fieldName) {
    if (this.params.containsKey(fieldName)) {
      return "=";
    }
    if (this.paramLikes.containsKey(fieldName)) {
      return " like ";
    }
    if (this.ltParams.containsKey(fieldName)) {
      return "<";
    }
    if (this.gtParams.containsKey(fieldName)) {
      return ">";
    }
    return "=";
  }

  public String getExpressionParam(String fieldName) {
    if (this.params.containsKey(fieldName)) {
      return "params";
    }
    if (this.paramLikes.containsKey(fieldName)) {
      return "paramLikes";
    }
    if (this.ltParams.containsKey(fieldName)) {
      return "ltParams";
    }
    if (this.gtParams.containsKey(fieldName)) {
      return "gtParams";
    }
    return "params";
  }

  public Map<String, Object> getGtParams()
  {
    return this.gtParams;
  }

  public Map<String, Object> getLtParams()
  {
    return this.ltParams;
  }

  static
  {
    MYSQL_SPECIAL_STR.put("/", "//");

    MYSQL_SPECIAL_STR.put("%", "/%");
    MYSQL_SPECIAL_STR.put("_", "/_");
  }

  public static class QueryInParam<E>
  {
    private List<E> list = new ArrayList();

    public QueryInParam(Collection<? extends E> c) {
      this.list.addAll(c);
    }

    public QueryInParam(E[] objects) {
      Collections.addAll(this.list, objects);
    }

    public String getArrayStr()
    {
      StringBuilder sb = new StringBuilder();
      for (Iterator i$ = this.list.iterator(); i$.hasNext(); ) { Object obj = i$.next();
        sb.append(obj.toString()).append(",");
      }

      return sb.substring(0, sb.length() - 1);
    }
  }

  public static enum DBOrder
  {
    DESC, ASC;

    String name;

    public String getName()
    {
      return this.name;
    }
  }

  public static class Between
  {
    Object begin;
    Object end;

    public Between(Object begin, Object end)
    {
      this.begin = begin;
      this.end = end;
    }

    public Object getBegin() {
      return this.begin;
    }

    public Object getEnd()
    {
      return this.end;
    }
  }
}